数据结构实验4,涉及哈希表、排序、优先队列相关问题,包含重要知识点的解析、解题思路和完整代码。
问题 A: 机器人王国里的路径长度
题目描述
在一个机器人王国里,围绕首都分N层构建卫星城市。以首都为圆心,以路相连分出两个卫星城在第一个层,然后每个卫星城又有路相连分出两个卫星城在下一层,但每条路的长度不同。第N层的卫星城不再分出新的卫星城。现在人类只探知到所有直接相连的城市间的路程,你能计算某个卫星城到达首都的路程吗?
输入
第一行为N,表示机器人王国里有N层卫星城,N最大为10。从第二行开始,共2N+1-2行,每行分别是城市的代号到其分出的卫星城的代号和它们间的路程。 代号用若干个字母表示,直连路程最大为100。最后一行是某卫星城的代号。
输出
根据最后一行的卫星城代号,求该卫星城到首都的路程。
样例输入
1 2 3 4 5 6 7 8
| 2 A F 20 B D 100 G A 5 G B 10 A C 6 B E 30 D
|
样例输出
问题分析
本题需要根据当前target不断向上回溯寻找其父节点,将distance值返回加入到总路程sum中即可,这里使用哈希表(unordered_map)存储每个城市的父城市和到父城市的距离。
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <iostream> #include <unordered_map> #include <string> #include <cmath> using namespace std; struct city { string parent; int distance; }; int main() { unordered_map<string, city> path; int N; cin >> N; int number = pow(2, N + 1) - 2; for (int i = 0;i < number;i ++) { string start, end; int distance; cin >> start >> end >> distance; path[end] = { start,distance }; } string target; cin >> target; int sum = 0; while (path.find(target)!=path.end()){ sum += path[target].distance; target = path[target].parent; } cout << sum << endl; return 0; }
|
注释
<unordered_map>是C++标准库中提供无序关联容器的头文件,它实现了基于哈希表的键值对存储结构,它具有以下特性:
- 元素无序存储,不会根据关键字值或映射值按任何特定顺序排序
- 键必须唯一(不允许重复键)
- 根据关键字来引用,而不是根据索引来引用
- 使用链表处理哈希冲突(链地址法)
构造哈希表:
1
| unordered_map<KeyType, ValueType> map_name;
|
- 元素访问:
| 成员函数 |
说明 |
map[key] |
访问或插入元素(键不存在时自动插入并值初始化) |
map.at(key) |
安全访问元素(键不存在时抛出out_of_range异常) |
map.find(key) |
返回指向元素的迭代器(未找到时返回end()) |
- 容量查询:
| 成员函数 |
说明 |
map.empty() |
判断容器是否为空 |
map.size() |
返回元素个数 |
- 修改操作:
| 成员函数 |
说明 |
map.insert({key, value}) |
插入键值对(返回pair<iterator, bool>) |
map.emplace(key, value) |
直接构造元素(避免临时对象) |
map.erase(key) |
删除指定键的元素 |
insert()&&emplace()的区别:
1
| map.insert({"apple", 2});
|
1
| map.emplace("apple", 3);
|
- 查找与统计
| 成员函数 |
说明 |
map.count(key) |
返回关键字出现的次数 |
map.contains(key) |
检查键是否存在(返回bool) |
问题 D: 寻找第二小的数
题目描述
求n个整数中第二小的数。
相同的整数看成一个数。比如,有5个数分别是1,1,3,4,5,那么第二小的数就是3。
输入
输入包含多组测试数据。输入的第一行是一个整数C,表示有C组测试数据;
每组测试数据的第一行是一个整数n,表示本组测试数据有n个整数(2<=n<=10),接着一行是n个整数(每个数均小于100)。
输出
为每组测试数据输出第二小的整数,如果不存在第二小的整数则输出“NO”,每组输出占一行。
样例输入
1 2 3 4 5 6 7
| 3 2 1 2 5 1 1 3 4 5 3 1 1 1
|
样例输出
问题分析
用逆序的优先队列即可完成!
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <iostream> #include <queue> using namespace std; void find() { priority_queue <int, vector<int>, greater<int>> pq; int m; cin >> m; for (int i = 0;i < m;i++) { int a; cin >> a; pq.push(a); } int min = pq.top(); pq.pop(); while (!pq.empty() && min == pq.top()) { pq.pop(); } if (pq.empty()) { cout << "NO" << endl; } else cout << pq.top() << endl; } int main() { int n; cin >> n; for (int i = 0;i < n;i++) { find(); } return 0; }
|
问题 E: 按十进制各位和排序
题目描述
对于给定的正整数序列,按照每个数的十进制形式各个位上的数之和从大到小排序,各个位上的数和相同的按照本身大小排序,大的在前,小的在后。
输入
第一行 1 个整数 n,表示序列的大小。( 0 < n ≤ 1000) 第二行 n 个正整数,表示序列的每个数,每个数不大于 100000000。
输出
输出按照题目要求排序后的序列。
样例输入
样例输出
问题分析
要将其十进制排序后的结果与原本大小匹配,这里使用了冒泡排序完成。
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <iostream> #include <vector> using namespace std; int Sum(int a) { int sum = 0; while (a != 0) { sum += a % 10; a = a / 10; } return sum; } int main() { int n; cin >> n; vector <int> order(n); for (int i = 0;i < n;i++) { cin >> order[i]; } for (int i = 0;i < n ; i++) { for (int j = 0 ;j < n-i-1;j++) { if (Sum(order[j]) < Sum(order[j + 1]) || (Sum(order[j]) == Sum(order[j + 1]) && order[j] < order[j + 1])) { int temp=order[j]; order[j]=order[j+1]; order[j+1]=temp; } } } for (int i = 0;i < n; i++) { cout<<order[i]<<" "; } return 0; }
|
问题 F: 奇偶数的排序
题目描述
给你10个正整数,其中5个奇数、5个偶数,先递减排奇数,然后再递增排偶数。请编程实现。
输入
一行10个正整数(int类型范围)。
输出
先递减排5个奇数,然后再递增排5个偶数,各个数之间有一个空格间隔。
样例输入
样例输出
问题分析
分别使用优先队列和逆序优先队列对奇数偶数进行排序,再依次输出队首元素。
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <iostream> #include <queue> #include <vector> using namespace std; int main() { priority_queue<int> odd; priority_queue <int, vector<int>, greater<int>> even; for (int i = 0;i < 10;i++) { int a; cin >> a; if (a % 2 == 0) { even.push(a); } else odd.push(a); } while(!odd.empty()) { cout << odd.top()<<" "; odd.pop(); } while (!even.empty() ){ cout << even.top()<<" "; even.pop(); } return 0; }
|
封面来源:: Learn Hash Tables in 13 minutes